#include "Config.h"

#include <Json.hpp>
#include <fstream>
#include <iostream>

void tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Config const& c) {
    jv = {
        {"server",
            {{"listenport", c.listenport},
                {"mysql",
                    {
                        {"hostname", c.mysql.hostname},
                        {"port", c.mysql.port},
                        {"username", c.mysql.username},
                        {"password", c.mysql.password},
                        {"database", c.mysql.database},
                    }}}},
        {"httpserver",
            {
                {"port", c.httpserver.port},
                {"doc_root", c.httpserver.doc_root},
                {"domain", c.httpserver.domain},
            }},
    };
}

Config tag_invoke(boost::json::value_to_tag<struct Config>, boost::json::value const& jv) {
    Config c{};

    boost::json::object obj = jv.as_object();
    auto server             = obj["server"].as_object();
    auto httpserver         = obj["httpserver"].as_object();

    boost::json::object mysql = server["mysql"].as_object();

    extract(server, c.listenport, "listenport");
    extract(mysql, c.mysql.hostname, "hostname");
    extract(mysql, c.mysql.port, "port");
    extract(mysql, c.mysql.username, "username");
    extract(mysql, c.mysql.password, "password");
    extract(mysql, c.mysql.database, "database");

    extract(httpserver, c.httpserver.port, "listenport");
    extract(httpserver, c.httpserver.doc_root, "doc_root");
    extract(httpserver, c.httpserver.domain, "domain");
    return c;
}

bool Config::loadConfig(std::string path) {
    try {
        // 打开 JSON 文件
        std::ifstream jsonFile(path);

        if (!jsonFile.is_open()) {
            std::cerr << "Failed to open JSON file." << std::endl;
            return false;
        }

        // 从文件中读取 JSON 数据到字符串
        std::string jsonString((std::istreambuf_iterator<char>(jsonFile)), std::istreambuf_iterator<char>());
        auto jv = boost::json::parse(jsonString);
        *this   = boost::json::value_to<Config>(jv);
    }
    catch (const std::exception& e) {
        std::cerr << e.what() << '\n';
    }
    return false;
}
